﻿// -------------------------------------------------------------------------
//    @FileName         :    NFExprCheckMacro.h
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-30
//    @Email			:    445267987@qq.com
//    @Module           :    NFExprCheckMacro
//    @Desc             :
//
// -------------------------------------------------------------------------

#pragma once

#include "NFExprCheck.h"

#define EXPR_CHECK_OVERFLOW(check, value) \
    do \
    { \
        if(check.IsOverflow()) \
        { \
            LOG_ERR(0, -1, "expr over flow calc value:{} real value:{} stack trace: {}", value, check.DebugString(), TRACE_STACK()); \
        }\
    } \
    while(0)

#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_2_PLUS(num1, num2) \
    EXPR_CHECK_OP_2_PLUS(num1, num2)
#else
    #define DEBUG_EXPR_CHECK_OP_2_PLUS(num1, num2) \

#endif

#define EXPR_CHECK_OP_2_PLUS(num1, num2) \
    EXPR_CHECK_OP_2(num1, num2, EN_EXPR_OP_PLUS, (num1 + num2))

//a - b
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_2_SUB(num1, num2) \
    EXPR_CHECK_OP_2_SUB(num1, num2)
#else
#define DEBUG_EXPR_CHECK_OP_2_SUB(num1, num2) \

#endif

#define EXPR_CHECK_OP_2_SUB(num1, num2) \
    EXPR_CHECK_OP_2(num1, num2, EN_EXPR_OP_SUB, (num1 - num2))

//a * b
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_2_MUL(num1, num2) \
    EXPR_CHECK_OP_2_MUL(num1, num2)
#else
#define DEBUG_EXPR_CHECK_OP_2_MUL(num1, num2) \

#endif

#define EXPR_CHECK_OP_2_MUL(num1, num2) \
    EXPR_CHECK_OP_2(num1, num2, EN_EXPR_OP_MUL, (num1 * num2))

//a / b
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_2_DIV(num1, num2) \
    EXPR_CHECK_OP_2_DIV(num1, num2)
#else
#define DEBUG_EXPR_CHECK_OP_2_DIV(num1, num2) \

#endif

#define EXPR_CHECK_OP_2_DIV(num1, num2) \
    EXPR_CHECK_OP_2(num1, num2, EN_EXPR_OP_DIV, (num1 / num2))

//a + b + c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_PLUS_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3_PLUS_PLUS(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_PLUS_PLUS(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_PLUS_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_PLUS, EN_EXPR_OP_PLUS, (num1 + num2 + num3))

//a + b - c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_PLUS_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3_PLUS_SUB(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_PLUS_SUB(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_PLUS_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_PLUS, EN_EXPR_OP_SUB, (num1 + num2 - num3))

//(a + b) * c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_PLUS_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3_PLUS_MUL(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_PLUS_MUL(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_PLUS_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_PLUS, EN_EXPR_OP_MUL, ((num1 + num2) * num3))

//(a + b) / c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_PLUS_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3_PLUS_DIV(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_PLUS_DIV(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_PLUS_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_PLUS, EN_EXPR_OP_DIV, ((num1 + num2) / num3))

//a - b + c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_SUB_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3_SUB_PLUS(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_SUB_PLUS(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_SUB_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_SUB, EN_EXPR_OP_PLUS, (num1 - num2 + num3))

//a - b - c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_SUB_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3_SUB_SUB(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_SUB_SUB(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_SUB_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_SUB, EN_EXPR_OP_SUB, (num1 - num2 - num3))

//(a - b) * c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_SUB_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3_SUB_MUL(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_SUB_MUL(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_SUB_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_SUB, EN_EXPR_OP_MUL, ((num1 - num2) * num3))

//(a - b) / c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_SUB_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3_SUB_DIV(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_SUB_DIV(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_SUB_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_SUB, EN_EXPR_OP_DIV, ((num1 - num2) / num3))

//a * b + c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_MUL_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3_MUL_PLUS(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_MUL_PLUS(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_MUL_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_MUL, EN_EXPR_OP_PLUS, (num1 * num2 + num3))

//a * b - c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_MUL_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3_MUL_SUB(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_MUL_SUB(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_MUL_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_MUL, EN_EXPR_OP_SUB, (num1 * num2 - num3))

//a * b * c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_MUL_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3_MUL_MUL(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_MUL_MUL(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_MUL_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_MUL, EN_EXPR_OP_MUL, (num1 * num2 * num3))

//a * b / c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_MUL_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3_MUL_DIV(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_MUL_DIV(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_MUL_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_MUL, EN_EXPR_OP_DIV, (num1 * num2 / num3))

//a / b + c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_DIV_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3_DIV_PLUS(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_DIV_PLUS(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_DIV_PLUS(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_DIV, EN_EXPR_OP_PLUS, (num1 / num2 + num3))

//a / b - c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_DIV_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3_DIV_SUB(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_DIV_SUB(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_DIV_SUB(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_DIV, EN_EXPR_OP_SUB, (num1 / num2 - num3))

//a / b * c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_DIV_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3_DIV_MUL(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_DIV_MUL(num1, num2, num3) \

#endif

#define EXPR_CHECK_OP_3_DIV_MUL(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_DIV, EN_EXPR_OP_MUL, (num1 / num2 * num3))

//a / b / c
#ifdef NF_DEBUG_MODE
#define DEBUG_EXPR_CHECK_OP_3_DIV_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3_DIV_DIV(num1, num2, num3)
#else
#define DEBUG_EXPR_CHECK_OP_3_DIV_DIV(num1, num2, num3) \

#endif


#define EXPR_CHECK_OP_3_DIV_DIV(num1, num2, num3) \
    EXPR_CHECK_OP_3(num1, num2, num3, EN_EXPR_OP_DIV, EN_EXPR_OP_DIV, (num1 / num2 / num3))

#define EXPR_CHECK_OP_2(num1, num2, op, value) \
    do \
    { \
        CExprCheck stCheck; \
        stCheck.PushNum(num1); \
        stCheck.PushNum(num2); \
        stCheck.PushOp(op); \
        stCheck.CalcExprInt64(); \
        EXPR_CHECK_OVERFLOW(stCheck, value); \
    } \
    while(0);

#define EXPR_CHECK_OP_3(num1, num2, num3, op1, op2, value) \
    do \
    { \
        CExprCheck stCheck; \
        stCheck.PushNum(num1); \
        stCheck.PushNum(num2); \
        stCheck.PushOp(op1); \
        stCheck.PushNum(num3); \
        stCheck.PushOp(op2); \
        stCheck.CalcExprInt64(); \
        EXPR_CHECK_OVERFLOW(stCheck, value); \
    } \
    while(0);